Overview
In this weeks assignment we will show how to create interactive plots
using the library called Plotly.
Plotly is a robust graphing library which will allow us to
display interactive, dynamic charts. Unlike static charts, interactive
graphs can allow us to convey much more information to a viewer in a
more engaging matter. The goal is to display data in such a way that the
user can easily interpret any patterns or correlations.
Interactive Plot -
2015 Data
Our first graph will convey the following information:
- A scatter plot showing the relation of
life expectancy
vs income.
- The size of a given dot is proportional to it’s
population size.
- Hover text will appear over a given point which will display the
country name and population size.
- Appropriate use of color and transparency for viewing ease.
For this graph, we will analyze data only from the year
2015. We can extract this information via the following
code:
subset_2015 <- subset(initial_data, Year == 2015)
The resulting data frame only has 2015 data:
Country Year Income life_expectancy region population
216 Afghanistan 2015 1750 57.9 Asia 33700000
435 Albania 2015 11000 77.6 Europe 2920000
654 Algeria 2015 13700 77.3 Africa 39900000
873 Andorra 2015 46600 82.5 Europe 78000
1092 Angola 2015 6230 64.0 Africa 27900000
Now, let’s view the interactive graph which meets the specifications
listed above.
# Create the scatter plot
plot <- plot_ly(data = subset_2015,
x = ~Income,
y = ~life_expectancy,
text = ~paste("Country: ", Country, "<br>Population Size: ", population),
color = ~Country,
size = ~population, sizes = c(5, 150),
marker = list(opacity = 0.6, line = list(color = 'black', width = 1))) %>%
layout(title = "Association between Life Expectancy and Income (2015)",
xaxis = list(title = "Income"),
yaxis = list(title = "Life Expectancy"),
hovermode = "closest")
# Show the plot
plot
NOTE: the proportional size of the point and
transparency levels were chosen via trial and error. Also,
hovermode being set to closest allows the user
to easily view country metadata without the cursor being exactly on a
given marker. This is helpful because some dots are quite
small.
Narrative - 2015
Data
The interactive graph has all the features we discussed. This allows
us to easily distinguish which countries have the highest population. We
can clearly see India, China, and the USA having very large populations
based on the size of their individual marker. It is also easy to see
that Japan, Switzerland, and Singapore all have the highest life
expectancy. Qatar has, by far, the most amount of avg income per person;
it must be nice to live there. Interestingly enough, there does
not seem to be a correlation between the amount of income an
individual makes for a given country, and the life expectancy. However,
it is interesting to note that, generally speaking, the African
countries have the lowest life expectancy, while the Asian countries
seem to have the highest.
Animated Graph
In this next section we will demonstrate how to show an animation for
scatter plots. We will use our original data set with all years up to
1950*, and cycle through each year to see how the data changes over
time.
*Note: we include up to 1950 because the income
starts to exponentially increase after those years. This causes for a
very skewed animation for the first 150 years.
The animated graph will have the following specifications:
- Cycle through each
year from 1800 to 1950.
- Highlight the relationship between
life expectancy and
population size.
- Use a custom, color-blind friendly color palette.
- Have the size of a given marker proportional to the
population size.
- Provide additional metadata when hovering over a marker.
The code is very similar to the previous interactive graph, with the
following additions:
- A much larger input data set.
- Add the binding for custom colors
- Cycle through the
year
Please view the code & animated plot below:
up_to_1950 <- subset(initial_data, Year <= 1950)
region_colors <- c("Africa" = "#000000", "Americas"="#E69F00", "Asia"="#56B4E9", "Europe"="#009E73", "Oceania"="#CC79A7");
# Create the animated scatter plot
animated_plot <- plot_ly(data = up_to_1950,
x = ~Income,
y = ~life_expectancy,
# Iterate through each year.
frame = ~Year,
text = ~paste("Country: ", Country, "<br>Population Size: ", population),
color = ~region,
# Custom color-blind friendly colos.
colors = region_colors,
size = ~population, sizes = c(10, 100),
marker = list(opacity = 0.6, line = list(color = 'black', width = 1))) %>%
layout(title = "Relationship between Life Expectancy and Income Over the Years",
xaxis = list(title = "Income"),
yaxis = list(title = "Life Expectancy"),
hovermode = "closest")
# Show the plot
animated_plot
Narration - Animated
Plot
From 1800-1900 we can see that the life expectancy (~20-40) and
income (<20k) really does not change that much for a given region. Of
course, there are a couple of exceptions in the late 1800s where a few
European countries start to increase their average life expectancy into
the mid 50s. What’s really interesting is how the life expectancy starts
to dramatically increase in the early 1900’s with the introduction of
penicillin and modern medicine. It is no surprise that first world
regions are the first to increase their life expectancy as they have
access to more doctors and modern medicine than a 3rd world
regions.
A fascinating pattern emerges if you examine the life expectancy from
1915 - 1925. The average life expectancy drops for every region by a
large margin. This is because of WW1. We see a similar pattern for life
expectancy from 1930 - 1950 with WW2. Initially, in the early 1930s,
only a few regions lower their life expectancy because of the isolated
invasions of Germany. However, by 1944, many regions drop
dramatically.
This goes to show that war has quite an effect on life expectancy
changes. This makes a lot of practical sense.
LS0tDQp0aXRsZTogIldlZWsgNiAtIEludGVyYWN0aXZpdHkgd2l0aCBQbG90bHkiDQphdXRob3I6ICJKYWNvYiBNYXJ0aW4iDQpkYXRlOiAiV2VzdCBDaGVzdGVyIFVuaXZlcnNpdHkgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgZmlnX3dpZHRoOiA2DQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgdGhlbWU6IHJlYWRhYmxlDQogICAgZmlnX2hlaWdodDogNA0KLS0tDQoNCmBgYHs9aHRtbH0NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoNCmRpdiNUT0MgbGkgew0KICAgIGxpc3Qtc3R5bGU6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLWNvbG9yOmxpZ2h0Z3JheTsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQogICAgZm9udC1mYW1pbHk6IEFyaWFsLCBIZWx2ZXRpY2EsIHNhbnMtc2VyaWY7DQogICAgY29sb3I6ICM3ODBjMGM7DQp9DQoNCi8qIG1vdXNlIG92ZXIgbGluayAqLw0KZGl2I1RPQyBhOmhvdmVyIHsNCiAgY29sb3I6IHJlZDsNCn0NCg0KLyogdW52aXNpdGVkIGxpbmsgKi8NCmRpdiNUT0MgYTpsaW5rIHsNCiAgY29sb3I6IGJsdWU7DQp9DQoNCg0KDQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMjRweDsNCiAgY29sb3I6IERhcmtibHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmOw0KICBmb250LXZhcmlhbnQtY2Fwczogbm9ybWFsOw0KfQ0KaDQuYXV0aG9yIHsgDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmg0LmRhdGUgeyANCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMSB7DQogICAgZm9udC1zaXplOiAyNHB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCmgyIHsNCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyANCiAgICBmb250LXNpemU6IDE1cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQovKiB1bnZpc2l0ZWQgbGluayAqLw0KYTpsaW5rIHsNCiAgY29sb3I6IGdyZWVuOw0KfQ0KDQovKiB2aXNpdGVkIGxpbmsgKi8NCmE6dmlzaXRlZCB7DQogIGNvbG9yOiBncmVlbjsNCn0NCg0KLyogbW91c2Ugb3ZlciBsaW5rICovDQphOmhvdmVyIHsNCiAgY29sb3I6IHJlZDsNCn0NCg0KLyogc2VsZWN0ZWQgbGluayAqLw0KYTphY3RpdmUgew0KICBjb2xvcjogeWVsbG93Ow0KfQ0KDQo8L3N0eWxlPg0KYGBgDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0Kb3B0aW9ucyhyZXBvcyA9IGxpc3QoQ1JBTj0iaHR0cDovL2NyYW4ucnN0dWRpby5jb20vIikpDQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KICAgbGlicmFyeSh0aWR5dmVyc2UpDQp9DQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoImNvd3Bsb3QiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygiY293cGxvdCIpDQogICBsaWJyYXJ5KGNvd3Bsb3QpDQp9DQppZiAoIXJlcXVpcmUoImxhdGV4MmV4cCIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJsYXRleDJleHAiKQ0KICAgbGlicmFyeShsYXRleDJleHApDQp9DQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KICAgbGlicmFyeShwbG90bHkpDQp9DQppZiAoIXJlcXVpcmUoImdhcG1pbmRlciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJnYXBtaW5kZXIiKQ0KICAgbGlicmFyeShnYXBtaW5kZXIpDQp9DQppZiAoIXJlcXVpcmUoInBuZyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygicG5nIikgICAgICAgICAgICAgIyBJbnN0YWxsIHBuZyBwYWNrYWdlDQogICAgbGlicmFyeSgicG5nIikNCn0NCmlmICghcmVxdWlyZSgiUkN1cmwiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoIlJDdXJsIikgICAgICAgICAgICMgSW5zdGFsbCBSQ3VybCBwYWNrYWdlDQogICAgbGlicmFyeSgiUkN1cmwiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJjb2xvdXJwaWNrZXIiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImNvbG91cnBpY2tlciIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJjb2xvdXJwaWNrZXIiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnaWZza2kiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImdpZnNraSIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJnaWZza2kiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJtYWdpY2siKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoIm1hZ2ljayIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJtYWdpY2siKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnckRldmljZXMiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImdyRGV2aWNlcyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJnckRldmljZXMiKQ0KfQ0KIyMjIGdncGxvdCBhbmQgZXh0ZW5zaW9ucw0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImdncGxvdDIiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZ2FuaW1hdGUiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImdnYW5pbWF0ZSIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJnZ2FuaW1hdGUiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZ3JpZGdlcyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dyaWRnZXMiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ2dyaWRnZXMiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJncmFwaGljcyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZ3JhcGhpY3MiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ3JhcGhpY3MiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJ0aWR5ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5ciIsIGRlcGVuZGVuY2llcyA9IFRSVUUpDQogICBsaWJyYXJ5KHRpZHlyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJyZXNoYXBlMiIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJyZXNoYXBlMiIsIGRlcGVuZGVuY2llcyA9IFRSVUUpDQogICBsaWJyYXJ5KHJlc2hhcGUyKQ0KfQ0KDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBUUlVFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkEpDQpgYGANCg0KIyMgT3ZlcnZpZXcNCkluIHRoaXMgd2Vla3MgYXNzaWdubWVudCB3ZSB3aWxsIHNob3cgaG93IHRvIGNyZWF0ZSBpbnRlcmFjdGl2ZSBwbG90cyB1c2luZyB0aGUgbGlicmFyeSBjYWxsZWQgYFBsb3RseWAuIFwNCmBQbG90bHlgIGlzIGEgcm9idXN0IGdyYXBoaW5nIGxpYnJhcnkgd2hpY2ggd2lsbCBhbGxvdyB1cyB0byBkaXNwbGF5IGludGVyYWN0aXZlLCBkeW5hbWljIGNoYXJ0cy4gVW5saWtlIHN0YXRpYyBjaGFydHMsIGludGVyYWN0aXZlIGdyYXBocyBjYW4gYWxsb3cgdXMgdG8gY29udmV5IG11Y2ggbW9yZSBpbmZvcm1hdGlvbiB0byBhIHZpZXdlciBpbiBhIG1vcmUgZW5nYWdpbmcgbWF0dGVyLiBUaGUgZ29hbCBpcyB0byBkaXNwbGF5IGRhdGEgaW4gc3VjaCBhIHdheSB0aGF0IHRoZSB1c2VyIGNhbiBlYXNpbHkgaW50ZXJwcmV0IGFueSBwYXR0ZXJucyBvciBjb3JyZWxhdGlvbnMuIA0KDQojIyBEYXRhIFRyYW5zZm9ybWF0aW9uIFJldmlldw0KSW4gPGEgaHJlZj0iaHR0cHM6Ly9qbWFydGluMTIuZ2l0aHViLmlvL1NUQVQ1NTMvd2Vla181L2phY29iX2Fzc2lnbm1lbnRfNS5odG1sIj5sYXN0IHdlZWsncyBhc3NpZ25tZW50PC9hPiwgaXQgd2FzIHNob3duIGhvdyB0byBkbyB2YXJpb3VzIGRhdGEgdHJhbnNmb3JtYXRpb25zIHVzaW5nIG1hbnkgZGF0YSBzZXRzLiBGb3IgdGhpcyB3ZWVrcyBncmFwaHMsIHRoZSBkYXRhIHNvdXJjZSB3aWxsIGJlIHJlLXVzaW5nIHRoZSBmaW5hbCBkYXRhIHNldCBmcm9tIHdlZWsgNS4NClwNClJlY2FsbCB0aGUgc3RydWN0dXJlIG9mIHRoZSBkYXRhc2V0LCB2aXN1YWxpemVkIGJlbG93OiANCg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KaW5pdGlhbF9kYXRhIDwtIHJlYWQuY3N2KCJqbV9maW5hbF9kYXRhLmNzdiIsIGhlYWRlciA9IFRSVUUpDQpoZWFkKGluaXRpYWxfZGF0YSwgNikNCmBgYA0KDQpJZiB5b3UgYXJlIHVuZmFtaWxpYXIgd2l0aCBob3cgd2UgZ290IHRoaXMgZGF0YSBzZXQsIGl0IGlzIGVuY291cmFnZWQgdG8gcmV2aWV3IHRoZSBgZGF0YSB0cmFuc2Zvcm1hdGlvbmAgc2VjdGlvbnMgb2YgPGEgaHJlZj0iaHR0cHM6Ly9qbWFydGluMTIuZ2l0aHViLmlvL1NUQVQ1NTMvd2Vla181L2phY29iX2Fzc2lnbm1lbnRfNS5odG1sIj53ZWVrIDU8L2E+LiANClwNClNpbXBseSBwdXQsIG91ciBkYXRhc2V0IGhhcyBpbmZvcm1hdGlvbiByZWxhdGluZyB0byBhIGNvdW50cnkgZm9yIGEgZ2l2ZW4geWVhci4gV2Ugd2lsbCBzaG93IGhvdyB0byBpbnRlcmFjdGl2ZWx5IHZpc3VhbGl6ZSB0aGlzIGRhdGEgc2V0LCBhcyBvcHBvc2VkIHRvIHRoZSBzdGF0aWMgY2hhcnRzIGZyb20gbGFzdCB3ZWVrLg0KDQojIyBJbnRlcmFjdGl2ZSBQbG90IC0gMjAxNSBEYXRhDQpPdXIgZmlyc3QgZ3JhcGggd2lsbCBjb252ZXkgdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbjoNCg0KMS4gQSBzY2F0dGVyIHBsb3Qgc2hvd2luZyB0aGUgcmVsYXRpb24gb2YgYGxpZmUgZXhwZWN0YW5jeWAgdnMgYGluY29tZWAuDQoyLiBUaGUgc2l6ZSBvZiBhIGdpdmVuIGRvdCBpcyBwcm9wb3J0aW9uYWwgdG8gaXQncyBgcG9wdWxhdGlvbmAgc2l6ZS4NCjMuIEhvdmVyIHRleHQgd2lsbCBhcHBlYXIgb3ZlciBhIGdpdmVuIHBvaW50IHdoaWNoIHdpbGwgZGlzcGxheSB0aGUgYGNvdW50cnkgbmFtZWAgYW5kIGBwb3B1bGF0aW9uYCBzaXplLiANCjQuIEFwcHJvcHJpYXRlIHVzZSBvZiBjb2xvciBhbmQgdHJhbnNwYXJlbmN5IGZvciB2aWV3aW5nIGVhc2UuDQpcDQpcDQoNCkZvciB0aGlzIGdyYXBoLCB3ZSB3aWxsIGFuYWx5emUgZGF0YSBvbmx5IGZyb20gdGhlIHllYXIgYDIwMTVgLiBXZSBjYW4gZXh0cmFjdCB0aGlzIGluZm9ybWF0aW9uIHZpYSB0aGUgZm9sbG93aW5nIGNvZGU6IA0KDQoNCmBgYHtyfQ0Kc3Vic2V0XzIwMTUgPC0gc3Vic2V0KGluaXRpYWxfZGF0YSwgWWVhciA9PSAyMDE1KQ0KYGBgDQpUaGUgcmVzdWx0aW5nIGRhdGEgZnJhbWUgb25seSBoYXMgMjAxNSBkYXRhOg0KYGBge3IgZWNobz1GQUxTRX0NCmhlYWQoc3Vic2V0XzIwMTUsIDUpDQpgYGANCg0KTm93LCBsZXQncyB2aWV3IHRoZSBpbnRlcmFjdGl2ZSBncmFwaCB3aGljaCBtZWV0cyB0aGUgc3BlY2lmaWNhdGlvbnMgbGlzdGVkIGFib3ZlLg0KDQpgYGB7cn0NCiMgQ3JlYXRlIHRoZSBzY2F0dGVyIHBsb3QNCnBsb3QgPC0gcGxvdF9seShkYXRhID0gc3Vic2V0XzIwMTUsDQogICAgICAgICAgICAgICAgeCA9IH5JbmNvbWUsDQogICAgICAgICAgICAgICAgeSA9IH5saWZlX2V4cGVjdGFuY3ksDQogICAgICAgICAgICAgICAgdGV4dCA9IH5wYXN0ZSgiQ291bnRyeTogIiwgQ291bnRyeSwgIjxicj5Qb3B1bGF0aW9uIFNpemU6ICIsIHBvcHVsYXRpb24pLA0KICAgICAgICAgICAgICAgIGNvbG9yID0gfkNvdW50cnksDQogICAgICAgICAgICAgICAgc2l6ZSA9IH5wb3B1bGF0aW9uLCBzaXplcyA9IGMoNSwgMTUwKSwgDQogICAgICAgICAgICAgICAgbWFya2VyID0gbGlzdChvcGFjaXR5ID0gMC42LCBsaW5lID0gbGlzdChjb2xvciA9ICdibGFjaycsIHdpZHRoID0gMSkpKSAlPiUNCiAgICAgICAgbGF5b3V0KHRpdGxlID0gIkFzc29jaWF0aW9uIGJldHdlZW4gTGlmZSBFeHBlY3RhbmN5IGFuZCBJbmNvbWUgKDIwMTUpIiwNCiAgICAgICAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJJbmNvbWUiKSwNCiAgICAgICAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJMaWZlIEV4cGVjdGFuY3kiKSwNCiAgICAgICAgICAgICAgIGhvdmVybW9kZSA9ICJjbG9zZXN0IikNCg0KIyBTaG93IHRoZSBwbG90DQpwbG90DQpgYGANCjxpPjxmb250IHNpemU9Mj5OT1RFOiB0aGUgcHJvcG9ydGlvbmFsIHNpemUgb2YgdGhlIHBvaW50IGFuZCB0cmFuc3BhcmVuY3kgbGV2ZWxzIHdlcmUgY2hvc2VuIHZpYSB0cmlhbCBhbmQgZXJyb3IuIEFsc28sIGBob3Zlcm1vZGVgIGJlaW5nIHNldCB0byBgY2xvc2VzdGAgYWxsb3dzIHRoZSB1c2VyIHRvIGVhc2lseSB2aWV3IGNvdW50cnkgbWV0YWRhdGEgd2l0aG91dCB0aGUgY3Vyc29yIGJlaW5nIGV4YWN0bHkgb24gYSBnaXZlbiBtYXJrZXIuIFRoaXMgaXMgaGVscGZ1bCBiZWNhdXNlIHNvbWUgZG90cyBhcmUgcXVpdGUgc21hbGwuPC9mb250PjwvaT4NCg0KIyMgTmFycmF0aXZlIC0gMjAxNSBEYXRhDQpUaGUgaW50ZXJhY3RpdmUgZ3JhcGggaGFzIGFsbCB0aGUgZmVhdHVyZXMgd2UgZGlzY3Vzc2VkLiBUaGlzIGFsbG93cyB1cyB0byBlYXNpbHkgZGlzdGluZ3Vpc2ggd2hpY2ggY291bnRyaWVzIGhhdmUgdGhlIGhpZ2hlc3QgcG9wdWxhdGlvbi4gV2UgY2FuIGNsZWFybHkgc2VlIEluZGlhLCBDaGluYSwgYW5kIHRoZSBVU0EgaGF2aW5nIHZlcnkgbGFyZ2UgcG9wdWxhdGlvbnMgYmFzZWQgb24gdGhlIHNpemUgb2YgdGhlaXIgaW5kaXZpZHVhbCBtYXJrZXIuIEl0IGlzIGFsc28gZWFzeSB0byBzZWUgdGhhdCBKYXBhbiwgU3dpdHplcmxhbmQsIGFuZCBTaW5nYXBvcmUgYWxsIGhhdmUgdGhlIGhpZ2hlc3QgbGlmZSBleHBlY3RhbmN5LiBRYXRhciBoYXMsIGJ5IGZhciwgdGhlIG1vc3QgYW1vdW50IG9mIGF2ZyBpbmNvbWUgcGVyIHBlcnNvbjsgaXQgbXVzdCBiZSBuaWNlIHRvIGxpdmUgdGhlcmUuIEludGVyZXN0aW5nbHkgZW5vdWdoLCB0aGVyZSBkb2VzIDxpPm5vdDwvaT4gc2VlbSB0byBiZSBhIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIGFtb3VudCBvZiBpbmNvbWUgYW4gaW5kaXZpZHVhbCBtYWtlcyBmb3IgYSBnaXZlbiBjb3VudHJ5LCBhbmQgdGhlIGxpZmUgZXhwZWN0YW5jeS4gSG93ZXZlciwgaXQgaXMgaW50ZXJlc3RpbmcgdG8gbm90ZSB0aGF0LCBnZW5lcmFsbHkgc3BlYWtpbmcsIHRoZSBBZnJpY2FuIGNvdW50cmllcyBoYXZlIHRoZSBsb3dlc3QgbGlmZSBleHBlY3RhbmN5LCB3aGlsZSB0aGUgQXNpYW4gY291bnRyaWVzIHNlZW0gdG8gaGF2ZSB0aGUgaGlnaGVzdC4NCg0KIyMgQW5pbWF0ZWQgR3JhcGgNCkluIHRoaXMgbmV4dCBzZWN0aW9uIHdlIHdpbGwgZGVtb25zdHJhdGUgaG93IHRvIHNob3cgYW4gYW5pbWF0aW9uIGZvciBzY2F0dGVyIHBsb3RzLiBXZSB3aWxsIHVzZSBvdXIgb3JpZ2luYWwgZGF0YSBzZXQgd2l0aCBhbGwgeWVhcnMgdXAgdG8gMTk1MCosIGFuZCBjeWNsZSB0aHJvdWdoIGVhY2ggeWVhciB0byBzZWUgaG93IHRoZSBkYXRhIGNoYW5nZXMgb3ZlciB0aW1lLiANCg0KPGk+PGZvbnQgc2l6ZT0xPipOb3RlOiB3ZSBpbmNsdWRlIHVwIHRvIDE5NTAgYmVjYXVzZSB0aGUgaW5jb21lIHN0YXJ0cyB0byBleHBvbmVudGlhbGx5IGluY3JlYXNlIGFmdGVyIHRob3NlIHllYXJzLiBUaGlzIGNhdXNlcyBmb3IgYSB2ZXJ5IHNrZXdlZCBhbmltYXRpb24gZm9yIHRoZSBmaXJzdCAxNTAgeWVhcnMuPC9pPjwvZm9udD4NCg0KVGhlIGFuaW1hdGVkIGdyYXBoIHdpbGwgaGF2ZSB0aGUgZm9sbG93aW5nIHNwZWNpZmljYXRpb25zOg0KDQoxLiBDeWNsZSB0aHJvdWdoIGVhY2ggYHllYXJgIGZyb20gMTgwMCB0byAxOTUwLg0KMi4gSGlnaGxpZ2h0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBgbGlmZSBleHBlY3RhbmN5YCBhbmQgYHBvcHVsYXRpb25gIHNpemUuDQozLiBVc2UgYSBjdXN0b20sIGNvbG9yLWJsaW5kIGZyaWVuZGx5IGNvbG9yIHBhbGV0dGUuDQo0LiBIYXZlIHRoZSBzaXplIG9mIGEgZ2l2ZW4gbWFya2VyIHByb3BvcnRpb25hbCB0byB0aGUgYHBvcHVsYXRpb25gIHNpemUuDQo1LiBQcm92aWRlIGFkZGl0aW9uYWwgbWV0YWRhdGEgd2hlbiBob3ZlcmluZyBvdmVyIGEgbWFya2VyLg0KDQpUaGUgY29kZSBpcyB2ZXJ5IHNpbWlsYXIgdG8gdGhlIHByZXZpb3VzIGludGVyYWN0aXZlIGdyYXBoLCB3aXRoIHRoZSBmb2xsb3dpbmcgYWRkaXRpb25zOg0KDQotIEEgbXVjaCBsYXJnZXIgaW5wdXQgZGF0YSBzZXQuDQotIEFkZCB0aGUgYmluZGluZyBmb3IgY3VzdG9tIGNvbG9ycw0KLSBDeWNsZSB0aHJvdWdoIHRoZSBgeWVhcmANCg0KUGxlYXNlIHZpZXcgdGhlIGNvZGUgJiBhbmltYXRlZCBwbG90IGJlbG93Og0KDQpgYGB7cn0NCnVwX3RvXzE5NTAgPC0gc3Vic2V0KGluaXRpYWxfZGF0YSwgWWVhciA8PSAxOTUwKQ0KDQpyZWdpb25fY29sb3JzIDwtIGMoIkFmcmljYSIgPSAiIzAwMDAwMCIsICJBbWVyaWNhcyI9IiNFNjlGMDAiLCAiQXNpYSI9IiM1NkI0RTkiLCAiRXVyb3BlIj0iIzAwOUU3MyIsICJPY2VhbmlhIj0iI0NDNzlBNyIpOw0KDQojIENyZWF0ZSB0aGUgYW5pbWF0ZWQgc2NhdHRlciBwbG90DQphbmltYXRlZF9wbG90IDwtIHBsb3RfbHkoZGF0YSA9IHVwX3RvXzE5NTAsDQogICAgICAgICAgICAgICAgeCA9IH5JbmNvbWUsDQogICAgICAgICAgICAgICAgeSA9IH5saWZlX2V4cGVjdGFuY3ksDQogICAgICAgICAgICAgICAgIyBJdGVyYXRlIHRocm91Z2ggZWFjaCB5ZWFyLg0KICAgICAgICAgICAgICAgIGZyYW1lID0gflllYXIsDQogICAgICAgICAgICAgICAgdGV4dCA9IH5wYXN0ZSgiQ291bnRyeTogIiwgQ291bnRyeSwgIjxicj5Qb3B1bGF0aW9uIFNpemU6ICIsIHBvcHVsYXRpb24pLA0KICAgICAgICAgICAgICAgIGNvbG9yID0gfnJlZ2lvbiwgDQogICAgICAgICAgICAgICAgIyBDdXN0b20gY29sb3ItYmxpbmQgZnJpZW5kbHkgY29sb3MuDQogICAgICAgICAgICAgICAgY29sb3JzID0gcmVnaW9uX2NvbG9ycywNCiAgICAgICAgICAgICAgICBzaXplID0gfnBvcHVsYXRpb24sIHNpemVzID0gYygxMCwgMTAwKSwgDQogICAgICAgICAgICAgICAgbWFya2VyID0gbGlzdChvcGFjaXR5ID0gMC42LCBsaW5lID0gbGlzdChjb2xvciA9ICdibGFjaycsIHdpZHRoID0gMSkpKSAlPiUNCiAgICAgICAgbGF5b3V0KHRpdGxlID0gIlJlbGF0aW9uc2hpcCBiZXR3ZWVuIExpZmUgRXhwZWN0YW5jeSBhbmQgSW5jb21lIE92ZXIgdGhlIFllYXJzIiwNCiAgICAgICAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJJbmNvbWUiKSwNCiAgICAgICAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJMaWZlIEV4cGVjdGFuY3kiKSwNCiAgICAgICAgICAgICAgIGhvdmVybW9kZSA9ICJjbG9zZXN0IikNCg0KIyBTaG93IHRoZSBwbG90DQphbmltYXRlZF9wbG90DQpgYGANCg0KIyMgTmFycmF0aW9uIC0gQW5pbWF0ZWQgUGxvdA0KRnJvbSAxODAwLTE5MDAgd2UgY2FuIHNlZSB0aGF0IHRoZSBsaWZlIGV4cGVjdGFuY3kgKH4yMC00MCkgYW5kIGluY29tZSAoPDIwaykgcmVhbGx5IGRvZXMgbm90IGNoYW5nZSB0aGF0IG11Y2ggZm9yIGEgZ2l2ZW4gcmVnaW9uLiBPZiBjb3Vyc2UsIHRoZXJlIGFyZSBhIGNvdXBsZSBvZiBleGNlcHRpb25zIGluIHRoZSBsYXRlIDE4MDBzIHdoZXJlIGEgZmV3IEV1cm9wZWFuIGNvdW50cmllcyBzdGFydCB0byBpbmNyZWFzZSB0aGVpciBhdmVyYWdlIGxpZmUgZXhwZWN0YW5jeSBpbnRvIHRoZSBtaWQgNTBzLiBXaGF0J3MgcmVhbGx5IGludGVyZXN0aW5nIGlzIGhvdyB0aGUgbGlmZSBleHBlY3RhbmN5IHN0YXJ0cyB0byBkcmFtYXRpY2FsbHkgaW5jcmVhc2UgaW4gdGhlIGVhcmx5IDE5MDAncyB3aXRoIHRoZSBpbnRyb2R1Y3Rpb24gb2YgcGVuaWNpbGxpbiBhbmQgbW9kZXJuIG1lZGljaW5lLiBJdCBpcyBubyBzdXJwcmlzZSB0aGF0IGZpcnN0IHdvcmxkIHJlZ2lvbnMgYXJlIHRoZSBmaXJzdCB0byBpbmNyZWFzZSB0aGVpciBsaWZlIGV4cGVjdGFuY3kgYXMgdGhleSBoYXZlIGFjY2VzcyB0byBtb3JlIGRvY3RvcnMgYW5kIG1vZGVybiBtZWRpY2luZSB0aGFuIGEgM3JkIHdvcmxkIHJlZ2lvbnMuDQpcDQpcDQpBIGZhc2NpbmF0aW5nIHBhdHRlcm4gZW1lcmdlcyBpZiB5b3UgZXhhbWluZSB0aGUgbGlmZSBleHBlY3RhbmN5IGZyb20gMTkxNSAtIDE5MjUuIFRoZSBhdmVyYWdlIGxpZmUgZXhwZWN0YW5jeSBkcm9wcyBmb3IgZXZlcnkgcmVnaW9uIGJ5IGEgbGFyZ2UgbWFyZ2luLiBUaGlzIGlzIGJlY2F1c2Ugb2YgV1cxLiBXZSBzZWUgYSBzaW1pbGFyIHBhdHRlcm4gZm9yIGxpZmUgZXhwZWN0YW5jeSBmcm9tIDE5MzAgLSAxOTUwIHdpdGggV1cyLiBJbml0aWFsbHksIGluIHRoZSBlYXJseSAxOTMwcywgb25seSBhIGZldyByZWdpb25zIGxvd2VyIHRoZWlyIGxpZmUgZXhwZWN0YW5jeSBiZWNhdXNlIG9mIHRoZSBpc29sYXRlZCBpbnZhc2lvbnMgb2YgR2VybWFueS4gSG93ZXZlciwgYnkgMTk0NCwgbWFueSByZWdpb25zIGRyb3AgZHJhbWF0aWNhbGx5LiANClwNClwNClRoaXMgZ29lcyB0byBzaG93IHRoYXQgd2FyIGhhcyBxdWl0ZSBhbiBlZmZlY3Qgb24gbGlmZSBleHBlY3RhbmN5IGNoYW5nZXMuIFRoaXMgbWFrZXMgYSBsb3Qgb2YgcHJhY3RpY2FsIHNlbnNlLg0K